////////////////////////////////////////////////////////////////////////////
//
//  CryEngine Source File.
//  Copyright (C), Crytek, 1999-2010.
// -------------------------------------------------------------------------
//  File name:	AssetBrowserSearchDlg.cpp
//  Version:	v1.00
//  Created:	12/07/2010 by Nicusor Nedelcu
//  Description:	Implementation of AssetBrowserSearchDlg.h
// -------------------------------------------------------------------------  
//  History:
//
//////////////////////////////////////////////////////////////////////////// 

#include "stdafx.h"
#include "AssetBrowserSearchDlg.h"
#include "AssetBrowserDialog.h"
#include "AssetMetaDataFileDB.h"
#include "AssetTags.h"

namespace AssetBrowser
{
	const UINT	kSearchFileFontSize = 120;
	const UINT	kSearchEditBoxMargin = 4;
	const char* kSearchTextDefault = "Type your search text here (you can use * and ? as wildcards)";
	const COLORREF kSearchTextDefaultForeColor = RGB( 150, 150, 150 );
	const COLORREF kSearchTextDefaultBackColor = RGB( 255, 255, 170 );
	const COLORREF kSearchTextForeColor = RGB( 0, 0, 0 );
	const COLORREF kSearchTextBackColor = RGB( 170, 255, 170 );
	const COLORREF kSearchNoResultsForeColor = RGB( 55, 0, 0 );
	const COLORREF kSearchNoResultsBackColor = RGB( 255, 70, 50 );
};

// CAssetBrowserSearchDlg dialog

IMPLEMENT_DYNAMIC(CAssetBrowserSearchDlg, CDialog)

CAssetBrowserSearchDlg::CAssetBrowserSearchDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CAssetBrowserSearchDlg::IDD, pParent)
{
	m_pAssetBrowserDlg = NULL;
	m_bForceFilterUsedInLevel = m_bForceShowFavourites = m_bForceHideLods = false;
}

CAssetBrowserSearchDlg::~CAssetBrowserSearchDlg()
{
	m_fntSearchText.DeleteObject();
}

void CAssetBrowserSearchDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDIT_SEARCH_TEXT, m_edSearchText);
}

BEGIN_MESSAGE_MAP(CAssetBrowserSearchDlg, CDialog)
	ON_EN_CHANGE(IDC_EDIT_SEARCH_TEXT, &CAssetBrowserSearchDlg::OnEnChangeEditSearchText)
	ON_WM_TIMER()
	ON_WM_SIZE()
END_MESSAGE_MAP()

// CAssetBrowserSearchDlg message handlers

BOOL CAssetBrowserSearchDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	assert(m_pAssetBrowserDlg);

	if( !m_pAssetBrowserDlg )
		return TRUE;

	m_fntSearchText.CreatePointFont( AssetBrowser::kSearchFileFontSize, "Arial Bold" );
	m_edSearchText.SetFont( &m_fntSearchText );
	m_edSearchText.SetWindowText( AssetBrowser::kSearchTextDefault );

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CAssetBrowserSearchDlg::OnCancel()
{
	// empty to prevent dialog closing on Esc key press
}

void CAssetBrowserSearchDlg::OnOK()
{
	// empty to prevent dialog closing on Enter key press
}

void CAssetBrowserSearchDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialog::OnSize( nType, cx, cy );

	if( m_edSearchText.GetSafeHwnd() )
	{
		m_edSearchText.SetWindowPos( 0, AssetBrowser::kSearchEditBoxMargin, AssetBrowser::kSearchEditBoxMargin, cx - AssetBrowser::kSearchEditBoxMargin*2, cy - AssetBrowser::kSearchEditBoxMargin*2, 0 );
	}
}

void CAssetBrowserSearchDlg::OnEnChangeEditSearchText()
{
	CString text = "";
	m_edSearchText.GetWindowText(text);
	if(!text.IsEmpty() && text[0] == ':')
		HandleDebugCommand(text.Right(text.GetLength()-1));
	else
		SetTimer( ID_TIMER_SEARCH_BY_FILENAME, AssetBrowser::kSearchByFilenameTimerDelay, NULL );
}

void CAssetBrowserSearchDlg::HandleDebugCommand(const CString& command)
{
	if(m_pAssetBrowserDlg == NULL)
		return;

	if(command.IsEmpty() || command[command.GetLength()-1] != ';')
		return;

	CString command1 = command.Left(command.GetLength()-1);

	CAssetTags& tagMgr = CAssetMetaDataFileDB::GetTagManager();

	int count = 0;
	CString cmd = command1.Tokenize(" ", count);
	CString arg = command1.Tokenize(" ", count);
	if(cmd.CompareNoCase("createtag") == 0 && !arg.IsEmpty())
	{
		if(tagMgr.TagExists(arg) == false)
			tagMgr.CreateTag(arg, false);
	}
	else if(cmd.CompareNoCase("createsharedtag") == 0 && !arg.IsEmpty())
	{
		if(tagMgr.TagExists(arg) == false)
			tagMgr.CreateTag(arg, true);
	}
	else if(cmd.CompareNoCase("destroytag") == 0 && !arg.IsEmpty())
	{
		if(tagMgr.TagExists(arg) == true)
			tagMgr.DestroyTag(arg);
	}
	else if(cmd.CompareNoCase("addtag") == 0 && !arg.IsEmpty())
	{
		if(tagMgr.TagExists(arg) == true)
		{
			TAssetItems assetItems;
			m_pAssetBrowserDlg->GetSelectedItems(assetItems);
			CAssetTags::StrVector assets;
			for(size_t i=0; i<assetItems.size(); ++i)
			{
				CString path = assetItems[i]->GetRelativePath();
				path += assetItems[i]->GetFilename();
				assets.push_back(path);
			}
			tagMgr.AddAssetsToTag(arg, assets);
		}
	}
	else if(cmd.CompareNoCase("removetag") == 0 && !arg.IsEmpty())
	{
		if(tagMgr.TagExists(arg) == true)
		{
			TAssetItems assetItems;
			m_pAssetBrowserDlg->GetSelectedItems(assetItems);
			CAssetTags::StrVector assets;
			for(size_t i=0; i<assetItems.size(); ++i)
			{
				CString path = assetItems[i]->GetRelativePath();
				path += assetItems[i]->GetFilename();
				assets.push_back(path);
			}
			tagMgr.RemoveAssetsFromTag(arg, assets);
		}
	}
	else if(cmd.CompareNoCase("showalltags") == 0)
	{
		CString message = "";
		CAssetTags::StrVector tags;
		tagMgr.GetAllTags(tags);
		for(size_t i=0; i<tags.size(); ++i)
		{
			CString line;
			line.Format("%s(%d,%s)\n", tags[i], tagMgr.GetAssetCountForTag(tags[i]), 
									tagMgr.IsTagShared(tags[i])?"shared":"local");
			message += line;
		}
		AfxMessageBox(message);
	}
	else if(cmd.CompareNoCase("showassets") == 0 && !arg.IsEmpty())
	{
		CString message = "";
		CAssetTags::StrVector assets;
		tagMgr.GetAssetsForTag(assets, arg);
		for(size_t i=0; i<assets.size(); ++i)
		{
			message += assets[i];
			message += "\n";
		}
		AfxMessageBox(message);
	}
	else if(cmd.CompareNoCase("showtags") == 0)
	{
		CString message = "";
		TAssetItems assetItems;
		m_pAssetBrowserDlg->GetSelectedItems(assetItems);
		for(size_t i=0; i<assetItems.size(); ++i)
		{
			CString path = assetItems[i]->GetRelativePath();
			path += assetItems[i]->GetFilename();
			
			message += path;
			message += ": ";

			CAssetTags::StrVector tags;
			tagMgr.GetTagsForAsset(tags, path);
			for(size_t k=0; k<tags.size(); ++k)
			{
				message += tags[k];
				message += " ";
			}
			message += "\n";
		}
		AfxMessageBox(message);
	}
}

void CAssetBrowserSearchDlg::OnTimer(UINT_PTR nIDEvent)
{
	if( nIDEvent == ID_TIMER_SEARCH_BY_FILENAME )
	{
		KillTimer( ID_TIMER_SEARCH_BY_FILENAME );

		static volatile bool s_bAlreadySearching = false;

		if( s_bAlreadySearching )
			return;

		assert( m_pAssetBrowserDlg );

		if( !m_pAssetBrowserDlg )
		{
			return;
		}

		s_bAlreadySearching = true;

		IAssetDisplayDatabase::TAssetFieldFiltersMap fields;

		for( size_t i = 0, iCount = m_fields.size(); i < iCount; ++i )
		{
			fields[m_fields[i].m_fieldName] = m_fields[i];
		}

		CString searchText, originalSearchText;

		m_edSearchText.GetWindowText( originalSearchText );
		bool bNoTextToSearch = false;

		searchText = originalSearchText;

		if( searchText == AssetBrowser::kSearchTextDefault )
		{
			searchText = "";
			bNoTextToSearch = true;
		}

		if( !searchText.IsEmpty() )
		{
			fields["fullsearchtext"].m_fieldName = "fullsearchtext";
			fields["fullsearchtext"].m_fieldType = SAssetField::eAssetFieldType_String;
			fields["fullsearchtext"].m_filterValue = searchText;
			fields["fullsearchtext"].m_filterCondition = SAssetField::eAssertFilterCondition_Contains;
		}

		//
		// also force other filters, which are usually found on the ribbon bar of the asset browser
		// kind of quick filtering checkboxes
		//
		if( m_bForceFilterUsedInLevel )
		{
			fields["usedinlevel"].m_fieldName = "usedinlevel";
			fields["usedinlevel"].m_fieldType = SAssetField::eAssetFieldType_Bool;
			fields["usedinlevel"].m_filterValue = m_bForceFilterUsedInLevel ? "Yes" : "No";
			fields["usedinlevel"].m_filterCondition = SAssetField::eAssertFilterCondition_Equal;
			fields["usedinlevel"].m_bPostFilter = true;
		}
		
		if( m_bForceShowFavourites )
		{
			fields["favourite"].m_fieldName = "favourite";
			fields["favourite"].m_fieldType = SAssetField::eAssetFieldType_Bool;
			fields["favourite"].m_filterValue = m_bForceShowFavourites ? "Yes" : "No";
			fields["favourite"].m_filterCondition = SAssetField::eAssertFilterCondition_Equal;
			fields["favourite"].m_bPostFilter = true;
		}

		if( m_bForceHideLods )
		{
			fields["islod"].m_fieldName = "islod";
			fields["islod"].m_fieldType = SAssetField::eAssetFieldType_Bool;
			fields["islod"].m_filterValue = m_bForceHideLods ? "No" : "Yes";
			fields["islod"].m_filterCondition = SAssetField::eAssertFilterCondition_Equal;
			fields["islod"].m_bPostFilter = true;
		}

		if( m_bAllowOnlyFilenames )
		{
			fields["fullfilepath"].m_fieldName = "fullfilepath";
			fields["fullfilepath"].m_fieldType = SAssetField::eAssetFieldType_String;
			fields["fullfilepath"].m_filterValue = m_allowedFilenames;
			fields["fullfilepath"].m_filterCondition = SAssetField::eAssertFilterCondition_ContainsOneOfTheWords;
		}

		//
		// this is the true magic happens, really, filtering the assets with the given field filters !
		//
		m_pAssetBrowserDlg->ApplyFilters( fields );

		//
		// we change the colors of the search edit control, based on the filtering results
		//
		if( m_pAssetBrowserDlg->m_oAssetViewer.GetAssetItems().empty() && !searchText.IsEmpty() )
		{
			m_edSearchText.m_bNotFound = true;
			m_edSearchText.SetTextColor( AssetBrowser::kSearchNoResultsForeColor );
			m_edSearchText.SetBkColor( AssetBrowser::kSearchNoResultsBackColor );
		}
		else
		{
			m_edSearchText.m_bNotFound = false;
			m_edSearchText.SetTextColor( bNoTextToSearch || ( originalSearchText.IsEmpty() && &m_edSearchText != GetFocus() ) ? AssetBrowser::kSearchTextDefaultForeColor : AssetBrowser::kSearchTextForeColor );
			m_edSearchText.SetBkColor( bNoTextToSearch || originalSearchText.IsEmpty() ? AssetBrowser::kSearchTextDefaultBackColor : AssetBrowser::kSearchTextBackColor );
		}

		s_bAlreadySearching = false;
	}

	CDialog::OnTimer(nIDEvent);
}

BEGIN_MESSAGE_MAP(CSearchEditCtrl, CColorCtrl<CEdit>)
	ON_CONTROL_REFLECT(EN_SETFOCUS, &CSearchEditCtrl::OnEnSetfocus)
	ON_CONTROL_REFLECT(EN_KILLFOCUS, &CSearchEditCtrl::OnEnKillfocus)
	ON_CONTROL_REFLECT(EN_UPDATE, &CSearchEditCtrl::OnEnUpdate)
END_MESSAGE_MAP()

CSearchEditCtrl::CSearchEditCtrl() : CColoredEdit()
{
	m_defaultText = AssetBrowser::kSearchTextDefault;
	SetTextColor( AssetBrowser::kSearchTextDefaultForeColor );
	SetBkColor( AssetBrowser::kSearchTextDefaultBackColor );
	m_bNotFound = false;
}

void CSearchEditCtrl::OnEnSetfocus()
{
	CString text;
	GetWindowText( text );

	if( text == m_defaultText )
	{
		SetWindowText( "" );
		SetTextColor( AssetBrowser::kSearchTextForeColor );
		SetBkColor( AssetBrowser::kSearchTextDefaultBackColor );
	}
}

void CSearchEditCtrl::OnEnKillfocus()
{
	CString text;
	GetWindowText( text );

	if( text == "" )
	{
		SetWindowText( m_defaultText );
		SetTextColor( AssetBrowser::kSearchTextDefaultForeColor );
		SetBkColor( AssetBrowser::kSearchTextDefaultBackColor );
	}
	else
	if( !m_bNotFound )
	{
		SetTextColor( AssetBrowser::kSearchTextForeColor );
		SetBkColor( AssetBrowser::kSearchTextBackColor );
	}
}

void CSearchEditCtrl::OnEnUpdate()
{
}
